#include <QApplication>
#include <QDir>

#include "qtprojectgeneratorfactory.h"
#include "rcbuildtask.h"
#include "rcsession.h"
#include "fileutilities.h"

#include "defines.h"

#include "rcmaemo5defines.h"
#include "rcmaemo5qtprojectgenerator.h"
#include "rcmaemo5settingsgui.h"

#include "common/networksettingsdialog.h"

#include "maemo5/maemo5statusupdater.h"

RcMaemo5QtProjectGenerator::RcMaemo5QtProjectGenerator(const QString       & platformId,
                                                       GeneratorOutputView & outputView,
                                                       QObject             * parent)
    : Maemo5QtProjectGenerator(outputView,
                               parent)
    , m_rcSession(NULL)
    , m_rcBuildTask(NULL)
{
    // the platform id is actually the wccParams plus a prefix
    m_wccParams = platformId.mid(QString(DYN_BUILDTARGET).length());

    m_generatorData.setRemotelyCompiled(true);
}


RcMaemo5QtProjectGenerator::~RcMaemo5QtProjectGenerator()
{
    delete m_rcBuildTask;
    m_rcBuildTask = NULL;
}


IStatusUpdater * RcMaemo5QtProjectGenerator::createStatusUpdater(QObject * parent)
{
    // TODO for now, we reuse the same status updater as Maemo5QtProjectGenerator
    //      later, we should probably need our own one. Reason: different amount
    //      of log messages, different way of providing pkgFileInfo() about a successful
    //      build, etc.
    return new Maemo5StatusUpdater(*this,
                                   parent);
}


void RcMaemo5QtProjectGenerator::build(const QString & widgetFile,
                                       RcSession     & rcSession)
{
    m_rcSession = &rcSession;

    if (!m_rcSession->isSignedOn())
    {
        NetworkSettingsDialog
            nsDlg(m_rcSession,
                  NULL);
        nsDlg.exec();

        if (!nsDlg.justSignedIn())
        {
            registerStatus(false);
            m_outputView.printOutput("Connecting to remote compiler failed.");
            emit finished(EXIT_FAILURE);
            return;
        }
    }

    Maemo5QtProjectGenerator::build(widgetFile,
                                    rcSession);
}


void RcMaemo5QtProjectGenerator::rebuild(RcSession     & rcSession)
{
    m_rcSession = &rcSession;

    // TODO factor out with the above code
    if (!m_rcSession->isSignedOn())
    {
        NetworkSettingsDialog
            nsDlg(m_rcSession,
                  NULL);
        nsDlg.exec();

        if (!nsDlg.justSignedIn())
        {
            registerStatus(false);
            m_outputView.printOutput("Connecting to remote compiler failed.");
            emit finished(EXIT_FAILURE);
            return;
        }
    }

    Maemo5QtProjectGenerator::rebuild(rcSession);
}


QString RcMaemo5QtProjectGenerator::getStatusText() const
{
    QString statusText;

    switch(m_currentGeneratorPhase.m_phase)
    {
    case RCM5_UNZIP_WIDGET:
        statusText = HAG_STATUS_EXTRACTING_WIDGET;
        break;
    case RCM5_DPKG_BUILDPACKAGE:
        statusText = "Starting remote build task";
        break;
    case RCM5_PKGZIPPING:
        statusText = "Zipping package to upload";
        break;
    case RCM5_PKGUPLOADING_WAITING:
        statusText = "Uploading & waiting for remote build";
        break;
    case RCM5_DOWNLOADING:
        statusText = "Downloading built package";
        break;
    case RCM5_INITIAL:
        statusText = HAG_STATUS_IDLE;
        break;
    case RCM5_ENDED_SUCCESSFULLY:
        statusText = HAG_STATUS_COMPLETED_OK;
        break;
    case RCM5_ENDED_WITH_ERRORS:
        statusText = HAG_STATUS_COMPLETED_NOTOK;
        break;
    }

    return statusText;
}


QWidget * RcMaemo5QtProjectGenerator::createSettingsWidget(const QString & widgetFile,
                                                           QWidget       * parent) const
{
    const QString
        TODO_COPYRIGHT_DIR("/templates/copyright/");

    QString
        copyrightDirPath = QApplication::applicationDirPath() + TODO_COPYRIGHT_DIR;

    QDir
        copyRightDir(copyrightDirPath);
    QList<QString>
        licenses = copyRightDir.entryList(QDir::Dirs
                                          | QDir::NoDotAndDotDot);

    // OBS (const_cast<RcMaemo5QtProjectGenerator*>(this))->sniffAppNames(widgetFile);
    QPair<QString, QString>
        appNames = FileUtilities::sniffAppNames(widgetFile);

    QWidget
        * rv = new RcMaemo5SettingsGui(licenses,
                                       // OBS m_appName,
                                       appNames.first,
                                       parent);

    return rv;
}


void RcMaemo5QtProjectGenerator::saveSettings(QWidget * settingsWidget) const
{
    RcMaemo5SettingsGui
        * rcMaemo5SettingsGui = dynamic_cast<RcMaemo5SettingsGui*>(settingsWidget);

    if (rcMaemo5SettingsGui != NULL)
    {
        rcMaemo5SettingsGui->saveSettings();
    }
}


QStringList RcMaemo5QtProjectGenerator::errorsForTarget(GeneratorTarget generatorTarget) const
{
    QStringList
        rv;

    QString
        forumNokiaUserName = Settings::get(Settings::ForumNokiaUserName).toString();
    int
        proxyConfig = Settings::get(Settings::ProxyConfig).toInt();

    if (forumNokiaUserName.length() == 0
        || proxyConfig == Settings::PCK_UndefinedProxyConfig)
    {
        rv.append("Network settings undefined");
    }

    QFile log(Settings::get(Settings::LogFilePath).toString());
    if (!log.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        // Failed to open the log file
        if (generatorTarget != NO_TARGET)
        {
            rv.append("Failed to open log file for writing! Check settings.");
        }
    }
    log.close();

    if (Settings::get(Settings::HybridAuthor).toString().length() == 0)
    {
        rv.append("Author is not set");
    }

    if (Settings::get(Settings::HybridEmail).toString().length() == 0)
    {
        rv.append("Author email is not set");
    }
    else
    {
        QRegExp
            validEmailRx("(\\w|\\.-)+@(\\w|\\.)+");
        if (validEmailRx.indexIn(Settings::get(Settings::HybridEmail).toString()) == -1)
        {
            rv.append("Author email is set, but seems broken");
        }
    }

    // TODO - check long and short descriptions too

    return rv;
}


void RcMaemo5QtProjectGenerator::startBuild()
{
    m_currentGeneratorPhase = RCM5_DPKG_BUILDPACKAGE;
    m_rcBuildTask = new RcBuildTask(this->m_outputView,
                                    *this->m_rcSession,
                                    this->m_appName,
                                    this->m_generatorData.projectDirectory(),
                                    this);
    connect(m_rcBuildTask,
            SIGNAL(buildCompleted(bool,QString)),
            this,
            SLOT(buildCompletedSlot(bool,QString)));
    connect(m_rcBuildTask,
            SIGNAL(zipping()),
            this,
            SLOT(zippingSlot()));
    connect(m_rcBuildTask,
            SIGNAL(uploadingAndWaiting()),
            this,
            SLOT(uploadingAndWaitingSlot()));
    connect(m_rcBuildTask,
            SIGNAL(downloading()),
            this,
            SLOT(downloadingSlot()));

    QDir
        dloadDir = this->m_generatorData.projectDirectory();
    dloadDir.cdUp();

    m_rcBuildTask->startBuilding(m_wccParams,
                                 dloadDir.absolutePath());
}


void RcMaemo5QtProjectGenerator::zippingSlot()
{
    m_currentGeneratorPhase = RCM5_PKGZIPPING;
}


void RcMaemo5QtProjectGenerator::uploadingAndWaitingSlot()
{
    m_currentGeneratorPhase = RCM5_PKGUPLOADING_WAITING;
}


void RcMaemo5QtProjectGenerator::downloadingSlot()
{
    m_currentGeneratorPhase = RCM5_DOWNLOADING;
}


void RcMaemo5QtProjectGenerator::buildCompletedSlot(bool    success,
                                                    QString downloadedFile)
{
    delete m_rcBuildTask;
    m_rcBuildTask = NULL;

    if (success)
    {
        m_currentGeneratorPhase = RCM5_ENDED_SUCCESSFULLY;
        m_outputView.printOutput(QString("Remote build succeeded, "
                                         "file downloaded to %1").arg(downloadedFile));
        emit finished(EXIT_SUCCESS);
    }
    else
    {
        m_currentGeneratorPhase = RCM5_ENDED_WITH_ERRORS;
        registerStatus(false);
        m_outputView.printOutput("Remote build failed.");
        emit finished(EXIT_FAILURE);
    }
}

